home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / comm.c < prev    next >
C/C++ Source or Header  |  1990-07-15  |  4KB  |  192 lines

  1. /* comm - select lines from two sorted files    Author: Martin C. Atkins */
  2.  
  3. /*
  4.  *    This program was written by:
  5.  *        Martin C. Atkins,
  6.  *        University of York,
  7.  *        Heslington,
  8.  *        York. Y01 5DD
  9.  *        England
  10.  *    and is released into the public domain, on the condition
  11.  *    that this comment is always included without alteration.
  12.  */
  13.  
  14. #include <sys/types.h>
  15. #include <fcntl.h>
  16.  
  17. #define BUFSIZ (512)
  18. #define LINMAX (600)
  19.  
  20. struct file {
  21.   char *name;            /* the file's name */
  22.   int fd;            /* the file descripter */
  23.   char buf[BUFSIZ];        /* buffer storage */
  24.   char *next;            /* the next character to read */
  25.   char *endp;            /* the first invalid character */
  26.   int seeneof;            /* an end of file has been seen */
  27. } files[2];
  28.  
  29. char lines[2][LINMAX];
  30.  
  31. int colflgs[3] = {1, 2, 3};    /* number of tabs + 1: 0 => no column */
  32.  
  33. static char *umsg = "Usage: comm [-[123]] file1 file2\n";
  34.  
  35. main(argc, argv)
  36. int argc;
  37. char *argv[];
  38. {
  39.   int cnt;
  40.   if (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
  41.     char *ap;
  42.     for (ap = &argv[1][1]; *ap; ap++) switch (*ap) {
  43.             case '1':
  44.             case '2':
  45.             case '3':
  46.             cnt = *ap - '1';
  47.             if (colflgs[cnt] == 0) break;
  48.             colflgs[cnt] = 0;
  49.             for (cnt++; cnt < 3; cnt++) colflgs[cnt]--;
  50.             break;
  51.             default:    usage();
  52.         }
  53.     argc--;
  54.     argv++;
  55.   }
  56.   if (argc != 3) usage();
  57.   eopen(argv[1], &files[0]);
  58.   eopen(argv[2], &files[1]);
  59.   comm();
  60.   exit(0);
  61. }
  62.  
  63. usage()
  64. {
  65.  
  66.   std_err(umsg);
  67.   exit(1);
  68. }
  69.  
  70. error(s, f)
  71. char *s, *f;
  72. {
  73.   std_err("comm: ");
  74.   std_err(s);
  75.   if (f) std_err(f);
  76.   std_err("\n");
  77.   exit(1);
  78. }
  79.  
  80. int eopen(fn, file)
  81. char *fn;
  82. struct file *file;
  83. {
  84.   file->name = fn;
  85.   file->next = file->endp = &file->buf[0];
  86.   file->seeneof = 0;
  87.   if (fn[0] == '-' && fn[1] == '\0')
  88.     file->fd = 0;
  89.   else if ((file->fd = open(fn, O_RDONLY)) < 0)
  90.     error("can't open ", fn);
  91. }
  92.  
  93.  
  94. int getbuf(file)
  95. struct file *file;
  96. {
  97. /* Get a buffer-full from the file.  Return true if no characters
  98.  * were obtained because we are at end of file.
  99.  */
  100.   int n;
  101.  
  102.   if (file->seeneof) return(1);
  103.   if ((n = read(file->fd, &file->buf[0], BUFSIZ)) < 0)
  104.     error("read error on ", file->name);
  105.   if (n == 0) {
  106.     file->seeneof++;
  107.     return 1;
  108.   }
  109.   file->next = &file->buf[0];
  110.   file->endp = &file->buf[n];
  111.   return(0);
  112. }
  113.  
  114.  
  115. int readline(fno)
  116. int fno;
  117. {
  118. /* Read up to the next '\n' character to buf.
  119.  * Return a complete line, even if end of file occurs within a line.
  120.  * Return false at end of file/
  121.  */
  122.   register struct file *file = &files[fno];
  123.   char *buf = lines[fno];
  124.  
  125.   if (file->next == file->endp && getbuf(file)) return(0);
  126.   while ((*buf++ = *file->next++) != '\n')
  127.     if (file->next == file->endp && getbuf(file)) {
  128.         *buf++ = '\n';
  129.         *buf = '\0';
  130.         return(1);
  131.     }
  132.   *buf = '\0';
  133.   return(1);
  134. }
  135.  
  136. comm()
  137. {
  138.   register int res;
  139.  
  140.   if (!readline(0)) {
  141.     cpycol(1);
  142.     return;
  143.   }
  144.   if (!readline(1)) {
  145.     putcol(0, lines[0]);
  146.     cpycol(0);
  147.     return;
  148.   }
  149.   for (;;) {
  150.     if ((res = strcmp(lines[0], lines[1])) != 0) {
  151.         res = res > 0;
  152.         putcol(res, lines[res]);
  153.         if (!readline(res)) {
  154.             putcol(!res, lines[!res]);
  155.             cpycol(!res);
  156.             return;
  157.         }
  158.     } else {
  159.         putcol(2, lines[0]);    /* files[1]lin == f2lin */
  160.         if (!readline(0)) {
  161.             cpycol(1);
  162.             return;
  163.         }
  164.         if (!readline(1)) {
  165.             putcol(0, lines[0]);
  166.             cpycol(0);
  167.             return;
  168.         }
  169.     }
  170.   }
  171.  
  172.   /* NOTREACHED */
  173. }
  174.  
  175. putcol(col, buf)
  176. int col;
  177. char *buf;
  178. {
  179.   int cnt;
  180.  
  181.   if (colflgs[col] == 0) return;
  182.   for (cnt = 0; cnt < colflgs[col] - 1; cnt++) prints("\t");
  183.   prints("%s", buf);
  184. }
  185.  
  186. cpycol(col)
  187. int col;
  188. {
  189.   if (colflgs[col]) while (readline(col))
  190.         putcol(col, lines[col]);
  191. }
  192.